<?php

/**
 All the functions related to manipulating files and folders.
*/

/**
 * copy uploaded file to the specified directory.
 */ 
function imce_copy_uploaded($set, $file) {
  //is the file real
  if (!is_uploaded_file($file['tmp_name']) || !isset($_SESSION['imcetotal'])) {
    drupal_set_message(t('No files were uploaded.'), 'error');
    return FALSE;
  }

  //move uploaded file to drupal's temp directory
  $temp = tempnam(file_directory_temp(), 'tmp_');
  if (!move_uploaded_file($file['tmp_name'], $temp)) {
    drupal_set_message(t('File upload error. Could not move uploaded file.'));
    return FALSE;
  }
  $file['tmp_name'] = $temp;

  //dont like too long filenames and files without an extension.
  $file['name'] = trim(basename($file['name']), '.');
  $file['name'] = strlen($file['name'])>48 ? substr($file['name'], -48) : $file['name']; //max filename lenght is 48
  if (!($dot = strrpos($file['name'], '.'))) {
    drupal_set_message(t('Invalid filename.'), 'error');
    return FALSE;
  }
  $extension = strtolower(substr($file['name'], $dot));

  //check image type and dimensions.
  if (in_array($extension, $GLOBALS['imce_ext']) && ($info = @getimagesize($file['tmp_name']))) {
    if (!in_array($info[2], array(1, 2, 3))) {// 1=gif, 2=jpg, 3=png. real file types
      drupal_set_message(t('Only images with .jpg, .gif, and .png extensions are allowed.'), 'error');
      return FALSE;
    }
    if ($info[0]>$set->width || $info[1]>$set->height) {
      if (($set->scale||$set->nolimit) && $_POST['scale']) {
        if(!image_scale($file['tmp_name'], $file['tmp_name'], $set->width, $set->height)) {
          drupal_set_message(t('Error scaling image.'), 'error');
          return FALSE;
        }
        clearstatcache();
        $file['size'] = filesize($file['tmp_name']);//new size
        $info = @getimagesize($file['tmp_name']);
        drupal_set_message(t('Image was scaled to allowed dimensions.'));
      }
      else if (!$set->nolimit) {
        drupal_set_message(t('Image dimensions exceed the limit.'), 'error');
        return FALSE;
      }
    }
  }
  // file is not an image. check if the extension is allowed
  else if ($set->extensions) {
    if (!in_array($extension, explode(',', str_replace(' ', '', $set->extensions)))) {
      drupal_set_message(t('Invalid file extension. Allowed extensions are .jpg, .gif, .png, !ext', array('!ext' => $set->extensions)), 'error');
      return FALSE;
    }
  }
  else if ($set->uid!=1) {//no limitation for user1 regarding non-image files.
    drupal_set_message(t('Only images with .jpg, .gif, and .png extensions are allowed.'), 'error');
    return FALSE;
  }

  //check quota, filesize.
  if ($file['size'] > $set->filesize*1024 && !$set->nolimit) {
    drupal_set_message(t('File size exceeds upload limit.'), 'error');
    return FALSE;
  }
  $newtotal = $file['size'] + $_SESSION['imcetotal'];
  if ($newtotal > $set->quota*1024 && !$set->nolimit) {
    drupal_set_message(t('You dont have enough free space.'), 'error');
    return FALSE;
  }

  //clear filename and copy file
  $cleared = preg_replace("/[^\w\-\_]/", '_', substr($file['name'], 0, $dot)).$extension;
  //$newpath = file_create_filename($cleared, $set->dir);
  $newpath = $set->dir . '/' . $cleared;
  //echo "<p>dest = $dest</p><p>$tmp_name = $file[tmp_name]</p>";
  if (file_exists($newpath)) {
    //backup old
    rename($newpath, imce_old_filename($newpath));
  }
  if (!@copy($file['tmp_name'], $newpath)) {
  //if (!@file_copy($file['tmp_name'], $dest, FILE_EXISTS_REPLACE)) {
    drupal_set_message(t('Error copying the file.'), 'error');
    return FALSE;
  }

  //success
  @chmod($newpath, 0664);
  $_SESSION['imcetotal'] = $newtotal;
  $_SESSION['imcelatest'] = $newpath;
  drupal_set_message(t('Upload successful.'));

  //thumbnails
  if ($_POST['thumb'] && $info && $set->twidth && $set->theight && ($set->twidth<$info[0] || $set->theight<$info[1])) {
    $aspect = $info[1] / $info[0];
    if ($aspect < $set->theight / $set->twidth) {
      $w = (int)min($set->twidth, $info[0]);
      $h = (int)round($w * $aspect);
    }
    else {
      $h = (int)min($set->theight, $info[1]);
      $w = (int)round($h / $aspect);
    }
    if (imce_resize_image($set, basename($newpath), $w, $h, TRUE)) {
      drupal_set_message(t('Thumbnail created.'));
    }
    else {
      drupal_set_message(t('Thumbnail can not be created.'), 'error');
    }
  }
  return TRUE;
}

/**
 * delete a file
 */
function imce_delete_file($set, $filename) {
  if (file_delete($set->dir.'/'.$filename)) {
    drupal_set_message(t('File deleted successfully.'));
    return TRUE;
  }
  drupal_set_message(t('Error deleting file.'), 'error');
  return FALSE;
}

function imce_rename_file($set, $filename, $newfilename) {
  if (strpos($newfilename,'/') !== FALSE || strlen($newfilename) == 0) {
    drupal_set_message(t('Error renaming file to ' . $newfilename), 'error');
    return FALSE;
  }
  //die('would rename now to ' . $set->dir.'/'.$newfilename);
  if (rename($set->dir.'/'.$filename, $set->dir.'/'.$newfilename)) {
    drupal_set_message(t('File renamed successfully.'));
    return TRUE;
  }
  drupal_set_message(t('Error renaming file.'), 'error');
  return FALSE;
}

/**
  * Resize file:$file in directory:$dir to dimensions $w x $h
  */
function imce_resize_image($set, $filename, $w, $h, $copy=FALSE) {
  //check if file exists
  $path = $set->dir.'/'.$filename;
  if (!is_file($path)) {
    drupal_set_message(t('File does not exist.'), 'error');
    return FALSE;
  }
  $_SESSION['imcelatest'] = $path;

  // check resize dimensions and file type
  if (!($dot = strrpos($filename, '.')) || !in_array(strtolower(substr($filename, $dot)), $GLOBALS['imce_ext'])) {
    drupal_set_message(t('File type is not supported.'), 'error');
    return FALSE;
  }
  if (!($w>0 && $h>0) || (($w>$set->width || $h>$set->height) && !$set->nolimit)) {
    drupal_set_message(t('Image dimensions exceed the limit.'), 'error');
    return FALSE;
  }

  //resize image to a temp file
  $temp = tempnam(file_directory_temp(), 'tmp_');
  if(!image_resize($path, $temp, $w, $h)) {
    drupal_set_message(t('Error resizing image.'), 'error');
    return FALSE;
  }

  //check quota
  $newtotal = $_SESSION['imcetotal'] + ($copy ? @filesize($temp) : @filesize($temp)-@filesize($path));
  if ($newtotal > $set->quota*1024 && !$set->nolimit) {
    drupal_set_message(t('You dont have enough free space.'), 'error');
    return FALSE;
  }

  //copy file
  $newpath = $copy ? file_create_filename($filename, $set->dir) : $path;
  if (!@copy($temp, $newpath)) {
    drupal_set_message(t('Error copying the file.'), 'error');
    return FALSE;
  }

  //success
  @chmod($newpath, 0664);
  $_SESSION['imcetotal'] = $newtotal;
  $_SESSION['imcelatest'] = $newpath;
  drupal_set_message(t('Resizing successful.'));
  return TRUE;
}

/**
 * scan directory and return file list and total size of dir.
 */
function imce_scan_directory($dir) {
  if (!is_dir($dir) || !is_readable($dir) || !($handle = @opendir($dir))) {
    drupal_set_message(t('Error opening directory'), 'error');
    return FALSE;
  }
  $directory = array('size' => 0, 'files' => array(), 'folders' => array());
  while(($file = readdir($handle)) !== FALSE) {
    if ($file == '.' || $file == '..' || $file == 'CVS' || $file == '.svn' || $file == '.htaccess') {
      continue;
    }
    if (is_dir($dir.'/'.$file)) {
      $directory['folders'][] = $file;
      continue;
    }
    $path = $dir.'/'.$file;
    $size = filesize($path);
    $ext = strtolower(substr($file, strrpos($file, '.')));
    $img = in_array($ext, $GLOBALS['imce_ext']) ? @getimagesize($path) : array(0, 0);
    $date = filemtime($path);
    $directory['files'][$path] = array('f'=>$file, 's'=>$size, 'w'=>(int)$img[0], 'h'=>(int)$img[1], 'd'=>$date);
    $directory['size'] += $size;
  }
  closedir($handle);
  return $directory;
}

/**
 * return working image directory.
 */
function imce_get_directory($set) {
  if ($set['shared']) {//use shared folder if it is declared
    $dir = file_directory_path().($set['shared']=='/' ? '' : '/'.$set['shared']);
  }
  else {//use personal folders by default.
    $dir = file_directory_path().'/'.$set['prefix'].$set['uid'];
  }
  if (file_check_directory($dir, TRUE)) {
    if ($set['subnav'] && $set['subdirs']) {
      foreach (explode(',', $set['subdirs']) as $sub) {
        $sub = $dir .'/'. trim($sub,'\\/ ');
        file_check_directory($sub, TRUE);
      }
    }
    return $dir;
  }
  exit(t('Directory error!').' - '.$dir. theme('status_messages'));//without a working directory imce is useless. so, terminate.
}


/**
 * Implementation of hook_file_download(). support for private downloads.
 */
function imce_file_download($file) {
  $roles = variable_get('imce_settings_roles', array());
  $roles += array('user1' => variable_get('imce_settings_user1', array()));
  $roles += array('default' => imce_settings_default());
  $imcefile = FALSE;
  foreach ($roles as $rid=>$set) {
    if ($set['shared']) {
      if ($set['shared'] == '/' || strpos($file, $set['shared'].'/') === 0) {
        $imcefile = TRUE;
        break;
      }
    }
    else {
      if (preg_match("/^".str_replace(array('/', '-'), array('\/', '\-'), $set['prefix'])."[0-9]+\//", $file)) {
        $imcefile = TRUE;
        break;
      }
    }
  }
  if ($imcefile && ($path = file_create_path($file))) {
    $ctype = ($info = @getimagesize($path)) ? $info['mime'] : (function_exists('mime_content_type') ? mime_content_type($path) : 'application/x-download');
    return array('Content-type: '. $ctype);
  }
}

function imce_old_filename($filename) {
  $i = strrpos($filename,'.');
  if ($i === FALSE) {
    return $filename . '.old';
  } else {
    return substr($filename, 0, $i) . '.old' . substr($filename, $i);
  }
}


/* 
 * Convert absolute paths to relative paths. return new path relative to the root.
 */
function imce_relative_path($path, $root=NULL) {
  $abs = str_replace('\\', '/', realpath($path));
  $root = str_replace('\\', '/', ($root ? realpath($root) : dirname(realpath($_SERVER['SCRIPT_FILENAME']))));
  return strpos($abs, $root)===0 ? trim(substr($abs, strlen($root)), '/') : substr($abs, (($pos=strpos($abs, '/')) ? $pos : 0));
}

/* 
 * convert file path to relative url.
 */
function imce_relative_url($path='') {
  if (variable_get('file_downloads', '')==FILE_DOWNLOADS_PRIVATE) {
    $file = trim(substr($path, strlen(file_directory_path())), '\\/');
    return url('system/files').(strlen($file) ? '/'.$file : '');
  }
  return base_path().$path;
}


/**
 * create folder(s) under root according to path.
 */
function imce_create_subfolders($path, $root) {
  $args = explode('/', str_replace('\\', '/', $path));
  $dirs = array($root);
  for ($i=0; strlen($arg=$args[$i]); $i++) {
    if (strpos($arg, '*')===FALSE) {//no asterisks. create the folder(s)
      for ($j=0; isset($dirs[$j]); $j++) {
        $dirs[$j] .= '/'. $arg;
        if (!file_check_location($dirs[$j], $root) || !file_check_directory($dirs[$j], TRUE)) {
          drupal_set_message(t('Specified path must be under file sytem path.'), 'error');
          return FALSE;
        }
      }
    }
    else {//get matching subfolders.
      $newdirs = array();
      $expr = str_replace('*', '.*', $arg);
      foreach ($dirs as $dir) {
        $newdirs = array_merge($newdirs, imce_get_subfolders($dir, $expr));
      }
      if (empty($newdirs)) {
        drupal_set_message(t('No matching sub-folders found.'), 'error');
        return FALSE;
      }
      $dirs = $newdirs;
    }
  }
  return TRUE;
}

/**
 * scan directory and return folders matching expression.
 */
function imce_get_subfolders($dir, $expr='') {
  $folders = array();
  if ($handle = @opendir($dir)) {
    while(($file = readdir($handle)) !== FALSE) {
      if ($file != '.' && $file != '..' && is_dir($dir.'/'.$file) && preg_match('/^'.$expr.'$/', $file)) {
        $folders[] = $dir.'/'.$file;
      }
    }
    closedir($handle);
  }
  return $folders;
}
